﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using SilverTile.Viewports;
using System.Windows.Media;
using System.Windows.Controls;

namespace SilverTile.Xaml
{
    public class SilverTileGame : ContentControl, IUpdateable
    {

        private DateTime _lastFrame;
        private Boolean _loaded;
        private Image _outputImage;

        public static readonly Random Rnd = new Random();

        public SilverTileGame()
        {
            CompositionTarget.Rendering += CompositionTarget_Rendering;
            _outputImage = new Image();
            this.Content = _outputImage;
            _lastFrame = DateTime.Now;
        }

        #region Properties

        public static new readonly DependencyProperty WidthProperty =
            DependencyProperty.RegisterAttached("Width", typeof(Int32), typeof(SilverTileGame),
                new PropertyMetadata(0, WidthHeightChanged));
        public new Int32 Width
        {
            get { return (Int32)GetValue(WidthProperty); }
            set { SetValue(WidthProperty, value); }
        }

        public static new readonly DependencyProperty HeightProperty =
          DependencyProperty.RegisterAttached("Height", typeof(Int32), typeof(SilverTileGame),
              new PropertyMetadata(0, WidthHeightChanged));
        public new Int32 Height
        {
            get { return (Int32)GetValue(HeightProperty); }
            set { SetValue(HeightProperty, value); }
        }

        private IViewport _viewport;
        public IViewport Viewport
        {
            get { return _viewport; }
            private set
            {
                _viewport = value;
                if (GameWorld != null)
                {
                    GameWorld.Viewport = _viewport;
                }
            }
        }

        private Boolean _running = false;
        public Boolean Running
        {
            get { return _running; }
            set { _running = value; }
        }

        private SilverTileGameWorld _gameWorld;
        public SilverTileGameWorld GameWorld
        {
            get { return _gameWorld; }
            set
            {
                _gameWorld = value;
                _gameWorld.Viewport = Viewport;
                if (!string.IsNullOrEmpty(_gameWorld.StartAreaName))
                {
                    ActiveGameArea = _gameWorld.GetGameArea(_gameWorld.StartAreaName);
                    _gameWorld.LoadSpawnPoints(ActiveGameArea);
                }
            }
        }

        public GameAreaGrid ActiveGameArea
        {
            get
            {
                if (GameWorld != null)
                {
                    return GameWorld.ActiveArea;
                }
                return null;
            }
            set
            {
                GameWorld.ActiveArea = value;
                if (Viewport != null)
                {
                    Viewport.SetGameArea(value);
                }
            }
        }

        #endregion

        private static void WidthHeightChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            SilverTileGame gameObject = (SilverTileGame)o;
            if (gameObject.Width > 0 && gameObject.Height > 0)
            {
                gameObject.Viewport = new Viewport(gameObject.Width, gameObject.Height);
                gameObject._outputImage.Source = gameObject.Viewport.Output;
                if (gameObject.ActiveGameArea != null)
                {
                    gameObject.Viewport.SetGameArea(gameObject.ActiveGameArea);
                }
            }
        }

        internal void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if (_running)
            {
                if (!_loaded)
                {
                    Load();
                }

                TimeSpan timeSinceLastFrame = DateTime.Now - _lastFrame;
                Update(timeSinceLastFrame);
                Render();                
                _lastFrame = DateTime.Now;

            }
        }

        public virtual void Load()
        {
            _loaded = true;
        }

        public virtual void Update(TimeSpan elapsedTime)
        {
            if (Viewport != null)
            {
                Viewport.Update(elapsedTime);
            }
            if (GameWorld != null)
            {
                GameWorld.Update(elapsedTime);
            }
        }

        public virtual void Render()
        {
            if (Viewport != null)
            {
                Viewport.Render();
            }
        }

    }
}
